package borge.web.teamspirit.client.page.team.widgets;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import borge.web.teamspirit.client.TeamSpirit;
import borge.web.teamspirit.client.interfaces.DataProvider;
import borge.web.teamspirit.client.interfaces.UserContentProvider;
import borge.web.teamspirit.client.interfaces.WidgetEventHandler;

import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.TextBoxBase;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DateBox;

/**
 * Superclass for widgets that uses a form interface to gather data from user
 * 
 * @author andreas
 * 
 */
public abstract class CreateDataWidget extends BaseWidget implements
        UserContentProvider, DataProvider {

    protected VerticalPanel iPanel;
    protected FlexTable iTable;
    protected Button iButton;
    protected Map<String, InputWrapper> iTableContent;
    private StringBuilder iErrors;
    private InputErrorWidget iErrorWidget;

    protected CreateDataWidget(WidgetEventHandler aEventHandler) {
        this();
        setWidgetEventHandler(aEventHandler);

    }

    protected CreateDataWidget() {

        iTable = new FlexTable();
        iTableContent = new HashMap<String, InputWrapper>();
        iButton = new Button(TeamSpirit.getConstants().send());
        iPanel = new VerticalPanel();
        iErrors = new StringBuilder();
    }

    /******** Utility methods for subclasses *********/

    protected TextBox createTextBox(Integer aVal, int aMaxLength) {

        if (aVal == null)
            return createTextBox("", aMaxLength);

        return createTextBox(aVal.toString(), aMaxLength);
    }

    protected TextBox createTextBox(String aText, int aMaxLength) {

        TextBox box = new TextBox();
        if (aText != null)
            box.setText(aText);

        box.setMaxLength(aMaxLength);

        return box;

    }

    /*
    protected DatePicker createDatePicker(Date aDate) {
        DatePicker picker = new DatePicker();
        //if (aDate != null)
            

        return picker;
    }*/


    protected DateBox createDateBox(Date aDate) {
        DateBox box = new DateBox();
        if (aDate != null)
            box.setValue(aDate);

        return box;
    }

    protected CheckBox createCheckBox(Boolean aValue) {

        CheckBox box = new CheckBox();
        if (aValue != null)
            box.setValue(aValue);

        return box;
    }

    protected TextArea createTextArea(String aText, int aWidth, int aHeight) {

        TextArea area = new TextArea();
        if (aText != null)
            area.setText(aText);

        area.setCharacterWidth(aWidth);
        area.setVisibleLines(aHeight);

        return area;
    }

    protected void addTableRow(int row, InputWrapper aInput) {

        int col = 0;
        iTableContent.put(aInput.getKey(), aInput);
        iTable.setText(row, col++, aInput.getKey());
        iTable.setWidget(row, col++, aInput.getWidget());

        if (aInput.isMandatory())
            iTable.setText(row, col, "*");

    }

    @SuppressWarnings("unchecked")
    protected void addArrayTableRow(int aRow, InputWrapper aInput) {

        int col = 0;

        iTable.setText(aRow, col++, aInput.getKey());
        ListBox box = new ListBox(false);

        for (int i = 0; i < aInput.getTexts().length; ++i) {

            Object[] texts = aInput.getTexts();
            if (texts instanceof Enum[]) {
                // Can ignore aValues array for enums
                box.addItem(texts[i].toString(), ((Enum) texts[i]).name());
            } else if (texts instanceof String[]) {
                box.addItem(texts[i].toString(), aInput.getValues()[i]
                        .toString());
            }
        }

        box.setSelectedIndex(aInput.getSelectedIndex());

        iTable.setWidget(aRow, col++, box);
        aInput.setWidget(box);
        iTableContent.put(aInput.getKey(), aInput);

        if (aInput.isMandatory())
            iTable.setText(aRow, col, "*");

    }

    protected void addButton(int row, int col, ClickHandler aHandler) {
        iButton.addClickHandler(aHandler);
        // iButton.addStyleName("gwt-Button");

        iTable.setWidget(row, col, iButton);
    }

    public void addErrorWidget() {

        if (iErrorWidget != null)
            iPanel.remove(iErrorWidget);

        iErrorWidget = new InputErrorWidget(iErrors.toString());
        iPanel.insert(iErrorWidget, 0);
        iErrors = new StringBuilder();
    }

    protected Map<String, InputWrapper> getTableData() {
        return iTableContent;
    }

    private void verifyStringInput(InputWrapper aInput, String aInputValue) {

        if (aInputValue == null) {
            if (aInput.isMandatory())
                iErrors.append("Mandatory field: " + aInput.getKey() + "\n");

            return;
        }

        if (aInput.isMandatory()) {
            if (aInputValue.length() < 1) {
                iErrors.append("Mandatory field: " + aInput.getKey() + "\n");
            }
        }

        if (aInput.getMin() != -1) {
            if (aInputValue.length() < aInput.getMin()) {
                iErrors.append("Field requires at least " + aInput.getMin()
                        + " characters: " + aInput.getKey());
            }
        }

        if (aInput.getMax() != -1) {
            if (aInputValue.length() > aInput.getMax()) {
                iErrors.append("Field allows at most " + aInput.getMax()
                        + " characters: " + aInput.getKey());
            }
        }

    }

    /******** Generic methods *********/
    
    public void handleSuccess(){
        //Window.alert("Success");
        Label label = new Label();
        label.setText("Successfully created player!");
        iPanel.remove(iTable);
        iPanel.add(label);
    }
    
    public void handleFailure(){
        //Window.alert("Failure");
        Label label = new Label();
        label.setText("Failed to create player!");
        iPanel.remove(iTable);
        iPanel.add(label);
    }
    
    /******** Implementation of UserContentProvider *********/

    public boolean foundInputErrors() {
        return iErrors.length() > 0;
    }

    public String getString(String key) {

        InputWrapper input = iTableContent.get(key);

        if (input == null)
            return null;

        Widget widget = input.getWidget();
        String res = null;
        if (widget instanceof TextBoxBase) {
            TextBoxBase box = (TextBoxBase) widget;
            if (box != null)
                res = box.getText();
        } else if (widget instanceof ListBox) {
            ListBox box = (ListBox) widget;
            if (box != null)
                res = box.getValue(box.getSelectedIndex());
        }

        verifyStringInput(input, res);

        return res;

    }

    public Date getDate(String key) {

        InputWrapper input = iTableContent.get(key);

        if (input == null)
            return null;

        DateBox box = (DateBox) input.getWidget();
        Date res = null;
        if (box != null)
            res = box.getDatePicker().getValue();

        if (input.isMandatory() && res == null) {
            iErrors.append("Mandatory field: " + key + "\n");
        }

        return res;
    }

    public Boolean getBoolean(String key) {

        InputWrapper input = iTableContent.get(key);

        if (input == null)
            return null;

        CheckBox box = (CheckBox) input.getWidget();
        if (box != null)
            return box.getValue();

        return null;
    }

    public Integer getInt(String aKey) {

        InputWrapper input = iTableContent.get(aKey);

        if (input == null)
            return null;

        String string = getString(aKey);
        if (string == null || string.length() == 0) {

            if (input.isMandatory()) {
                iErrors.append("Mandatory field: " + aKey + "\n");
            }

            return null;
        }

        try {
            Integer i = Integer.parseInt(string);
            return i;
        } 
        catch (Exception e) {
            // what to do here?
            iErrors.append("Invalid input: " + string
                    + ". Field must contain numbers only: " + aKey);
        }

        return null;
    }

    // Its not certain that this class will be the provider
    public UserContentProvider getUserContentProvider() {
        return this;
    }
}
